/*
 * 文件名：BeanUtils.java
 * 版权：© Copyright 2012-2018 广州宝锶信息技术有限公司
 * 创建人：曾毅
 * 创建时间：2016年7月6日 下午3:41:04
 * 修改人：
 * 修改时间：
 * 需改内容：
 * 
 */
package com.baothink.weichat.utils;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
 * bean工具类
 * 
 * @author  曾毅
 * @version 1.0，2016年7月6日 下午3:41:04
 * @since   ASSCCommon1.0
 */
public class BeanUtil {
    
    /**  
     * 获取指定属性的值
     * 
     * @param bean
     * @param pro
     * @return
     * @since ASSCCommon1.0
     */
    public static Object getValueByPro(Object bean,Object pro){
        Object value="";
        try {
            if(null==pro||null == bean){
                return "";
            }
            String propertyStr = pro.toString();
            Map<String, PropertyDescriptor> propertyDescriptors = getPropertyDescriptors(bean);
            if(null!=propertyDescriptors&&propertyDescriptors.containsKey(propertyStr)){
            	PropertyDescriptor propertyDescriptor = propertyDescriptors.get(propertyStr);
            	Method readMethod = propertyDescriptor.getReadMethod();
            	return readMethod.invoke(bean, new Object[]{});
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return value;
    }
    
    /**  
     * 获取指定属性集的值 
     * 返回List
     * 
     * @param t
     * @param clz
     * @param properties
     * @return
     * @since ASSCCommon1.0
     */
    @SuppressWarnings("unchecked")
    public static <T> List<Object> getValuesListByPros(T t, Class<T> clz,String...properties){
       return (List<Object>) getValuesByPros(t,clz,Type.List,null,false,properties);
    }
    
    /**  
     *  获取指定属性集的值 
     * 返回Map
     * 
     * @param t
     * @param clz
     * @param properties
     * @return
     * @since ASSCCommon1.0
     */
    @SuppressWarnings("unchecked")
    public static <T> List<Object> getValuesMapByPros(T t, Class<T> clz,String...properties){
        return (List<Object>) getValuesByPros(t,clz,Type.Map,null,false,properties);
    }
    
    /**  
     *  获取指定属性集的值 
     * 返回Array
     * 
     * @param t
     * @param clz
     * @param properties
     * @return
     * @since ASSCCommon1.0
     */
    public static <T> Object[] getValuesArrayByPros(T t, Class<T> clz,String...properties){
        return (Object[]) getValuesByPros(t,clz,Type.Array,null,false,properties);
    }
    
    /**  
     * 获取集合对象指定属性集的值 
     * 
     * @param list
     * @param clz
     * @param handler
     * @param properties
     * @return
     * @since ASSCCommon1.0
     */
    public static <T> List<Object[]> getValuesArrayByPros(List<T> list, Class<T> clz,BeanValueHandler handler,String...properties){
        List<Object[]> objs=new ArrayList<Object[]>();
        if(null==list){
            return objs;
        }
        for (T t : list) {
            Object[] vals = (Object[]) getValuesByPros(t, clz,Type.Array,handler,false,properties);
            objs.add(vals);
        }
        return objs;
    }
    
    /**  
     *  获取指定属性集的值 
     * 
     * @param t
     * @param clz
     * @param handler
     * @param filterEmpty
     * @param properties
     * @return
     * @since ASSCCommon1.0
     */
    @SuppressWarnings("unchecked")
    public static <T> List<Object> getValuesListByPros(T t, Class<T> clz,BeanValueHandler handler,boolean filterEmpty,String...properties){
        return (List<Object>) getValuesByPros(t,clz,Type.List,handler,filterEmpty,properties);
    }
    
    /**  
     * 通过实例属性获取对应值 
     * 
     * @param t  实例
     * @param clz 实例类型
     * @param type 返回集类型
     * @param handler 值处理
     * @param filterEmpty 是否过滤为空的值
     * @param properties  要获取值的属性集
     * @return
     * @since ASSCCommon1.0
     */
    public static <T> Object getValuesByPros(T t, Class<T> clz,Type type,BeanValueHandler handler,boolean filterEmpty,String...properties){
        Map<String,Object> resultMap=null;
        List<Object> resultList=null;
        try {
            resultMap=new HashMap<String,Object>();
            resultList=new ArrayList<Object>();
            Map<String,Method> beanProMethodsMap=new HashMap<String,Method>();
            BeanInfo beanInfo = Introspector.getBeanInfo(clz);
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
                String name = propertyDescriptor.getName();
                Method writeMethod = propertyDescriptor.getReadMethod();
                beanProMethodsMap.put(name, writeMethod);
            }
            
            for (String pro : properties) {
                if(!StringUtil.isEmptyOrNull(pro)){
                    Method method=beanProMethodsMap.get(pro);
                    if(null==method){
                        throw new Exception("the method of property \""+pro+"\" is not found!");
                    }
                    Object value = method.invoke(t);
                    
                    if(null!=handler){
                        value=handler.formatValue(pro,value);
                    }
                    if(filterEmpty&&null==value){
                        continue;
                    }
                    resultMap.put(pro, value);
                    resultList.add(value);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        switch (type.ordinal()) {
            case 0:
                return resultList;
            case 1:
                return resultMap;
            case 2:
                return resultList.toArray();
            default:
                return resultMap;
        }
    }
    
    
    public static void writeValueByPro(Object o ,String pro,Object value) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException{
    	Map<String, PropertyDescriptor> propertyDescriptors = getPropertyDescriptors(o);
    	pro = !StringUtil.isEmptyOrNull(pro)?pro.toLowerCase():"";
    	if(null!=propertyDescriptors&&propertyDescriptors.containsKey(pro)){
    		PropertyDescriptor propertyDescriptor = propertyDescriptors.get(pro);
    		Method writeMethod = propertyDescriptor.getWriteMethod();
    		writeMethod.invoke(o, value);
    	}
    }
    
    /**  
     * 获取对象所有属性的PropertyDescriptor
     * 
     * @param obj
     * @return
     * @since ASSCCommon1.0
     */
    public static Map<String,PropertyDescriptor> getPropertyDescriptors(Object obj){
       return getPropertyDescriptors(obj.getClass());
    }
    
    /**  
     * 获取对象所有属性的PropertyDescriptor
     * 
     * @param obj
     * @return
     * @since ASSCCommon1.0
     */
    public static Map<String,PropertyDescriptor> getPropertyDescriptors(Class<?> clz){
        Map<String,PropertyDescriptor> reMap=new HashMap<String,PropertyDescriptor>();
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(clz);
            
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
                String name=propertyDescriptor.getName();
                if(name.equals("class")){
                    continue;
                }
                reMap.put(name.toLowerCase(), propertyDescriptor);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return reMap;
    }
    
    public static interface BeanValueHandler{
        Object formatValue(String pro,Object value);
    }
    
    public static enum Type{
        List,Map,Array;
    }
}
